package cmd

import (
	"bytes"
	"fmt"
	ico "github.com/biessek/golang-ico"
	"github.com/nfnt/resize"
	"image"
	_ "image/gif"
	_ "image/jpeg"
	"image/png"
	_ "image/png"
	"os"
	"path/filepath"
	"strings"
)

func doConvert(src string, dst string, sizes []uint, coverFlag bool) (string, error) {
	// 参数设置
	var CompressFlag = false

	// 检查输入文件是否存在
	if _, err := os.Stat(src); err != nil {
		return "", fmt.Errorf("匹配的输入文件不存在: %s", src)
	}

	// 传入此方法的 dst 一定表示一个 输出文件路径
	if cerr := CreateParentDirectories(dst); cerr != nil {
		return "", cerr
	}

	// cover 表示生成输出文件时是否覆盖已经存在的文件

	//srcBase := filepath.Base(src)
	//srcExt := filepath.Ext(src)

	// 读取PNG文件
	input, _ := os.Open(src)
	defer input.Close()
	//img, err := png.Decode(input)
	img, _, err := image.Decode(input)
	if err != nil || img == nil {
		return "", fmt.Errorf("failed to decode image: %v", err)
	}

	// 生成多尺寸ICO
	if len(sizes) == 0 {
		sizes = []uint{256}
	}
	var icons []image.Image
	for _, size := range sizes {
		icons = append(icons, resize.Resize(size, size, img, resize.Lanczos3))
	}

	// 用于返回的输入文件描述
	// 如果只生成1个文件, 直接返回输出文件路径
	// 否则, 返回一段类似通配符的文件路径, 描述生成的多规格 icon 路径
	showOutputFiles := ""

	// 从 dst 解析出文件名不含后缀
	parentDir := filepath.Dir(dst)
	dstBase := strings.Split(filepath.Base(dst), ".")[0]
	dstExt := filepath.Ext(dst)
	if len(icons) == 1 {
		showOutputFiles = dst
	} else {
		// 对于多个 sizes, 生成一个字符串.形如 64|128|512
		showOutputFiles = filepath.Join(parentDir, dstBase+"_"+JoinUintSlice(sizes, "|")+dstExt)
	}

	// 创建一个 PNG 编码器并设置压缩等级
	var pngEncoder png.Encoder
	if CompressFlag {
		pngEncoder = png.Encoder{
			CompressionLevel: png.BestCompression,
		}
	}

	// 循环创建 ico 文件
	for _, icon := range icons {
		if len(icons) > 1 {
			dstName := fmt.Sprintf("%s_%d%s", dstBase, icon.Bounds().Dx(), dstExt)
			dst = filepath.Join(parentDir, dstName)
		}

		if !coverFlag {
			// 如果未开启覆盖文件, 则要安全地获取一个不存在的文件路径
			dst = GenerateUniqueFilePath(dst)
			if len(icons) == 1 { // 更新返回的输出文件路径
				showOutputFiles = dst
			}
		}

		output, _ := os.Create(dst)
		defer output.Close()

		if !CompressFlag {
			// 写入 ICO 文件 (不压缩)
			if err := ico.Encode(output, icon); err != nil {
				return "", fmt.Errorf("error encoding icon: %v \n", err)
			}
		} else {
			// 使用临时 buffer 存储 PNG 数据
			var pngData bytes.Buffer
			if err := pngEncoder.Encode(&pngData, icon); err != nil {
				return "", fmt.Errorf("failed to encode PNG: %v", err)
			}

			// 写入 ICO 文件
			if err := ico.Encode(output, icon); err != nil {
				return "", fmt.Errorf("error encoding icon: %v", err)
			}
		}
	}

	return showOutputFiles, nil
}
